/****

    activequant - activestocks.eu

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

	
	contact  : contact@activestocks.eu
    homepage : http://www.activestocks.eu

 ****/
package org.activequant.calendar;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import org.activequant.core.types.TimeStamp;
import org.activequant.util.calendar.CalendarUtils;

/**
 * A calendar entry that will last a complete single day. <br/>
 * AllDayCalendarEntry implements ICalendarEntry. Holds the following associated variables:
 * <ul>
 * <li>entryStartAsMillis(long)</li>
 * <li>entryEndAsMillis(long)</li>
 * </ul>
 * <b>History:</b><br>
 * - [Jun 21, 2008] Created (mark)<br>
 * 
 * @author mark
 */
public class AllDayCalendarEntry implements ICalendarEntry {
	/**
	 * private final long entryStartAsMillis;
	 */
	private final long entryStartAsMillis;
	/**
	 * private final long entryEndAsMillis;
	 */
	private final long entryEndAsMillis;

	/**
	 * Create a new all day calendar entry.<br/>
	 * constructs an AllDayCalendarEntry (implements ICalendarEntry).<br/>
	 * Sets its associated entryStartAsMillis(long) and entryEndAsMillis(long) with the start(midnight) and end(last millisecond) of the day in the given when(long) (using GMT timezone) 
	 * @param when
	 *            the time stamp in milliseconds since the Epoch of which the day part determines the all day calendar
	 *            entry.
	 */
	public AllDayCalendarEntry(final long when) {
		Calendar calendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
		calendar.setTimeInMillis(when);

		this.entryStartAsMillis = CalendarUtils.toMidnight(calendar).getTimeInMillis();
		this.entryEndAsMillis = CalendarUtils.toEndOfDay(calendar).getTimeInMillis();
	}
	/**
	 * returns the associated entryStartAsMillis(long)
	 */
	public long getStartOfEntryAsMillis() {
		return this.entryStartAsMillis;
	}
	/**
	 * returns the associated entryEndAsMillis(long)
	 */
	public long getEndOfEntryAsMillis() {
		return this.entryEndAsMillis;
	}
	/**
	 * returns a String representation of this AllDayCalendarEntry (implements ICalendarEntry) in the form:<br/>
	 * "${this.class.name}: ${entryStartCal}"<br/>
	 * , where entryStartCal is a GMT Calendar using the associated entryStartAsMillis(long) formatted as:<br/>
	 * "${YEAR}-${MONTH}-${DAY_OF_MONTH}T${HOUR_OF_DAY}:${MINUTE}:${SECOND} ${MILLISECOND} ${TimeZone}"
	 */
	@Override
	public String toString() {
		Calendar calendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
		calendar.setTimeInMillis(this.entryStartAsMillis);

		return this.getClass().getName() + ": " + CalendarUtils.calendarToString(calendar);
	}
	/**
	 * returns whether the given now(TimeStamp) is during the day defined by this AllDayCalendarEntry.<br/>
	 * Checks whether the last midnight of the given now(TimeStamp) matches the associated entryStartAsMillis(long) (which always points to midnight - (T00:00 000))
	 */
	public boolean isDuring(final TimeStamp now) {
		final long nowInMillis = CalendarUtils.getLastMidnight(now).getNanoseconds() / CalendarUtils.NANOS_TO_MILLIS;
		return this.entryStartAsMillis == nowInMillis;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (int) (this.entryEndAsMillis ^ (this.entryEndAsMillis >>> 32));
		result = prime * result + (int) (this.entryStartAsMillis ^ (this.entryStartAsMillis >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AllDayCalendarEntry other = (AllDayCalendarEntry) obj;
		if (this.entryEndAsMillis != other.entryEndAsMillis)
			return false;
		if (this.entryStartAsMillis != other.entryStartAsMillis)
			return false;
		return true;
	}

}
